package multithread.waitandnotify;

public class WaitAndNotifyTest {
    static  class Calculator extends Thread {
        int total;
        @Override
        public void run() {
            synchronized (this){
                for(int i = 0; i < 101; i++){
                    total += i;
                }
                System.out.println("开始通知");
                this.notify();
                System.out.println("结束通知");//唤醒需要等待这个Notify的线程结束了
            }
        }
    }

     static class ReaderResult extends Thread {
         Calculator c;

         public ReaderResult(Calculator c) {
             this.c = c;
         }

         @Override
         public void run() {
             synchronized (c) {
                 try {
                     System.out.println(Thread.currentThread() + "等待计算结...");
                     c.wait();
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 System.out.println(Thread.currentThread() + "计算结果为:" + c.total);
             }
         }
     }

    /**
     * 测试结果满足预期，c对象的等待队列的线程，能被计算线程通知，要满足是同一个对象 wait/notify
     */
    public static void testWaitFirstRun(){
         Calculator calculator = new Calculator();
         //先启动获取计算结果线程
         new ReaderResult(calculator).start();
         calculator.start();
     }

    /**
     * 一直死循环：Thread[Thread-1,5,main]等待计算结...
     *
     *可以看出ReaderResult在Calculator上等待。发生这个现象就是常说的通知丢失，在获取通知前，通知提前到达，我们先计算结果，计算完后再通知，
     * 但是这个时候获取结果没有在等待通知，等到获取结果的线程想获取结果时，这个通知已经通知过了，
     * 所以就发生丢失，那我们该如何避免?可以设置变量表示是否被通知过，修改代码如下：
     * 改造参考WaitNotifyTest2
     */
    public static void testNotifyFirstRun(){
        Calculator calculator = new Calculator();

        calculator.start();

        //先启动获取计算结果线程
        new ReaderResult(calculator).start();

    }

    public static void main(String[] args) {
        testWaitFirstRun();
    }
}
